/**
 * @author Huynh
 * Last modified by Huynh on April 02, 2012
 * 
 * TODO: Improve game AI.
 */

package model;


public class CompPlayer extends Player {
	public static int MAX_DEPTH = 4;
	private int player;
	private int[] dropOrder = { 3, 2, 4, 1, 5, 0, 6 };

	public CompPlayer(Game game, int player) {
		this.player = player;
	}

	@Override
	public int getMove(int column, Game game) {
		BoardStructure board = game.getBoard();
		int bestWorst = -BoardStructure.INFINITY;
		int bestColumn = -1;

		// Select the center column if this is the first move.
		if (board.getNumberOfPiece() == 0
				|| (board.getNumberOfPiece() == 1 && board.getCell(3, 0) != -1)) {
			return 3;
		}

		// Simulate a drop in each of the columns and see the result.
		for (int col = 0; col < 7; col++) {
			int currentColumn = dropOrder[col];

			// Push a new game into the stack.
			Game newGame = game.makeGame();

			// If this is not a valid move, choose another column.
			if (!newGame.isValidMove(currentColumn)) {
				continue;
			}

			// Make the move.
			newGame.move(currentColumn);

			// If this drop win the game, take it.
			if (newGame.getWinner() == player) {
				return currentColumn;
			}

			// Otherwise, look ahead to see how good this move is.
			int goodness = evaluate(player, MAX_DEPTH, -BoardStructure.INFINITY,
					BoardStructure.INFINITY, newGame);

			// is this move is better than the previous move, remember it.
			if (goodness > bestWorst) {
				bestWorst = goodness;
				bestColumn = currentColumn;
			}
		}
		return bestColumn;
	}

	// Evaluate a move
	int evaluate(int player, int depth, int alpha, int beta, Game currentState) {
		//If the current player is the winner, then return the best result.
		if (currentState.getWinner() == player){
			return BoardStructure.INFINITY - MAX_DEPTH + depth;
		}else if (currentState.getWinner() == (1- player)){
			return - BoardStructure.INFINITY + MAX_DEPTH - depth;
		}else if (currentState.isOver()){ //Draw
			return 0;
		}else if (depth == 0){
			return currentState.getGoodness(player);
		}
		
		//Assume that it is the other player's turn.
		int best = -BoardStructure.INFINITY;
		int maxab = alpha;
		
		for (int col = 0; col < 7; col++){
			//Make a new game to try on.
			Game newGame = currentState.makeGame();
			if (newGame.isValidMove(dropOrder[col])){
				newGame.move(dropOrder[col]);
			}
			
			//The other player will choose the best result for him.
			int goodness = evaluate(1 - player, depth - 1, - beta, -maxab, newGame);
			
			if (goodness > best){//The other player may choose this move.
				best = goodness;
				if (best > maxab)
					maxab = best;
			}
			
			if (best > beta){
				break;
			}
		}	
		
		return -best;
	}// End function evaluate.
}
